import sys
import os
import json
import datetime
import re
from pathlib import Path
from docx import Document

# 设置输出缓冲区为无缓冲，确保日志实时输出
sys.stdout.reconfigure(line_buffering=True) if hasattr(sys.stdout, 'reconfigure') else None

# 定义一个更好的日志函数
def log(message, level="INFO"):
    """输出带时间戳和级别的日志到stderr"""
    timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")[:-3]
    print(f"[{timestamp}] [{level}] {message}", file=sys.stderr)
    # 强制刷新错误输出缓冲区
    sys.stderr.flush()

# 自定义JSON编码器，处理特殊类型
class NaNEncoder(json.JSONEncoder):
    def default(self, obj):
        # 处理日期时间类型
        if isinstance(obj, (datetime.date, datetime.datetime)):
            return obj.isoformat()
        # 处理浮点数，保留5位小数
        elif isinstance(obj, float):
            return round(obj, 5)
        # 处理其他类型
        try:
            return super().default(obj)
        except TypeError:
            return str(obj)


def parse_legacy_placeholder(placeholder, data_mapping):
    """
    解析旧格式的占位符（向后兼容）
    Args:
        placeholder: 占位符字符串
        data_mapping: 数据映射字典
    Returns:
        解析出的值或None
    """
    # 解析占位符，例如 v5c4s1b 或 v5c4s3mb
    if len(placeholder) < 6:
        print(f"跳过无效占位符: {placeholder}，长度小于6", file=sys.stderr)
        return None
        
    # 检查是否是多字符字段标识符 (如 mb, md, mf, mh, mj, ml)
    if len(placeholder) >= 8 and placeholder[-2:] in ['mb', 'md', 'mf', 'mh', 'mj', 'ml', 'mn']:
        # 提取前缀 (v5c4s3)
        prefix = placeholder[:-2]
        # 提取字段标识符 (mb, md, mf, mh, mj, ml)
        field_id = placeholder[-2:]
    else:
        # 提取前缀 (v5c4s1)
        prefix = placeholder[:-1]
        # 提取字段标识符 (b, c, e, f, g, i)
        field_id = placeholder[-1]
    
    print(f"旧格式占位符解析: {placeholder}, 前缀: {prefix}, 字段标识符: {field_id}", file=sys.stderr)
    
    # 检查前缀是否存在于数据映射中
    if prefix in data_mapping:
        data = data_mapping[prefix]
        print(f"找到数据映射: {prefix}", file=sys.stderr)
        value = None
        
        # 根据字段标识符获取对应的值
        if isinstance(data, dict):
            print(f"数据类型: 字典", file=sys.stderr)
            if field_id == 'b':
                value = data.get('region2压强峰值/kPa')
                print(f"字段'b': region2压强峰值/kPa = {value}", file=sys.stderr)
            elif field_id == 'c':
                value = data.get('region3压强峰值/kPa')
                print(f"字段'c': region3压强峰值/kPa = {value}", file=sys.stderr)
            elif field_id == 'e':
                value = data.get('左右侧压强峰值偏差')
                print(f"字段'e': 左右侧压强峰值偏差 = {value}", file=sys.stderr)
            elif field_id == 'f':
                value = data.get('region2平均压强/kPa')
                print(f"字段'f': region2平均压强/kPa = {value}", file=sys.stderr)
            elif field_id == 'g':
                value = data.get('region3平均压强/kPa')
                print(f"字段'g': region3平均压强/kPa = {value}", file=sys.stderr)
            elif field_id == 'i':
                value = data.get('左右侧平均压强偏差')
                print(f"字段'i': 左右侧平均压强偏差 = {value}", file=sys.stderr)
            elif field_id == 'mb':
                # 处理七区数据中的1区或臀部左右数据
                if prefix.endswith('s2'):
                    value = data.get('1')
                    print(f"字段'mb': 七区数据regio4 = {value}", file=sys.stderr)
                elif prefix.endswith('s1'):
                    value = data.get('value')
                    print(f"字段'mb': 臀部左右_max行_region1压强峰值 = {value}", file=sys.stderr)
            elif field_id == 'md':
                value = data.get('3')
                print(f"字段'md': 七区数据region5 = {value}", file=sys.stderr)
            elif field_id == 'mf':
                value = data.get('5')
                print(f"字段'mf': 七区数据region6 = {value}", file=sys.stderr)
            elif field_id == 'mh':
                value = data.get('7')
                print(f"字段'mh': 七区数据region7 = {value}", file=sys.stderr)
            elif field_id == 'mj':
                value = data.get('9')
                print(f"字段'mj': 七区数据region8 = {value}", file=sys.stderr)
            elif field_id == 'ml':
                value = data.get('11')
                print(f"字段'ml': 七区数据region9 = {value}", file=sys.stderr)
            elif field_id == 'mn':
                value = data.get('13')
                print(f"字段'mn': 七区数据region10 = {value}", file=sys.stderr)
            else:
                print(f"未知字段标识符: {field_id}", file=sys.stderr)
        else:
            print(f"数据类型不匹配: {type(data)}", file=sys.stderr)
        
        return value
    else:
        print(f"在数据映射中未找到前缀: {prefix}", file=sys.stderr)
        return None

def fill_table_placeholders(cell, data_mapping):
    """
    填充表格单元格中的占位符
    Args:
        cell: docx表格单元格对象
        data_mapping: 数据映射字典
    """
    if not cell.text:
        return
    
    # 查找形如 {v5c4s1b} 或 {v5c4ls5} 的占位符
    placeholders = re.findall(r'\{([^}]+)\}', cell.text)
    
    if placeholders:
        print(f"在表格中找到{len(placeholders)}个占位符: {', '.join(placeholders)}", file=sys.stderr)
    
    for placeholder in placeholders:
        print(f"处理占位符: {placeholder}", file=sys.stderr)
        
        # 直接检查占位符是否在数据映射中
        if placeholder in data_mapping:
            value = data_mapping[placeholder]
            print(f"找到直接映射: {placeholder} -> {value}", file=sys.stderr)
            
            # 替换占位符
            if value is not None:
                # 检查是否为变化百分比数据（占位符包含'chg'）
                if 'chg' in placeholder and isinstance(value, (int, float)):
                    # 将变化百分比格式化为百分数（假设原始数据已经是百分比形式，如0.15表示15%）
                    formatted_value = f"{round(value * 100, 2)}%"
                    print(f"替换变化百分比占位符 {{{placeholder}}} 为百分数格式: {formatted_value}", file=sys.stderr)
                elif isinstance(value, float):
                    formatted_value = str(round(value, 5))
                    print(f"替换占位符 {{{placeholder}}} 为值: {formatted_value}", file=sys.stderr)
                else:
                    formatted_value = str(value)
                    print(f"替换占位符 {{{placeholder}}} 为值: {formatted_value}", file=sys.stderr)
                
                # 在run级别进行替换，保持run结构
                for paragraph in cell.paragraphs:
                    for run in paragraph.runs:
                        if '{' + placeholder + '}' in run.text:
                            run.text = run.text.replace('{' + placeholder + '}', formatted_value)
            else:
                print(f"值为None，将占位符 {{{placeholder}}} 设置为隐藏文本", file=sys.stderr)
                for paragraph in cell.paragraphs:
                    for run in paragraph.runs:
                        if run.text == '{' + placeholder + '}':
                            run.font.hidden = True
        else:
            # 尝试解析旧格式的占位符（向后兼容）
            value = parse_legacy_placeholder(placeholder, data_mapping)
            if value is not None:
                # 检查是否为变化百分比数据（占位符包含'chg'）
                if 'chg' in placeholder and isinstance(value, (int, float)):
                    # 将变化百分比格式化为百分数（假设原始数据已经是百分比形式，如0.15表示15%）
                    formatted_value = f"{round(value * 100, 2)}%"
                    print(f"通过旧格式解析替换变化百分比占位符 {{{placeholder}}} 为百分数格式: {formatted_value}", file=sys.stderr)
                elif isinstance(value, float):
                    formatted_value = str(round(value, 5))
                    print(f"通过旧格式解析替换占位符 {{{placeholder}}} 为值: {formatted_value}", file=sys.stderr)
                else:
                    formatted_value = str(value)
                    print(f"通过旧格式解析替换占位符 {{{placeholder}}} 为值: {formatted_value}", file=sys.stderr)
                
                for paragraph in cell.paragraphs:
                    for run in paragraph.runs:
                        if '{' + placeholder + '}' in run.text:
                            run.text = run.text.replace('{' + placeholder + '}', formatted_value)
            else:
                # 如果找不到对应的数据，设置为隐藏文本
                print(f"在数据映射中未找到占位符: {placeholder}，将设置为隐藏文本", file=sys.stderr)
                for paragraph in cell.paragraphs:
                    for run in paragraph.runs:
                        if run.text == '{' + placeholder + '}':
                            run.font.hidden = True


def fill_paragraph_placeholders(paragraph, data_mapping):
    """
    填充段落中的占位符
    Args:
        paragraph: docx段落对象
        data_mapping: 数据映射字典
    """
    if not paragraph.text:
        return
    
    # 查找形如 {v5c4s1b} 或 {v5c4ls5} 的占位符
    placeholders = re.findall(r'\{([^}]+)\}', paragraph.text)
    
    if placeholders:
        print(f"在段落中找到{len(placeholders)}个占位符: {', '.join(placeholders)}", file=sys.stderr)
    
    for placeholder in placeholders:
        print(f"处理占位符: {placeholder}", file=sys.stderr)
        
        # 直接检查占位符是否在数据映射中
        if placeholder in data_mapping:
            value = data_mapping[placeholder]
            print(f"找到直接映射: {placeholder} -> {value}", file=sys.stderr)
            
            # 替换占位符
            if value is not None:
                # 检查是否为变化百分比数据（占位符包含'chg'）
                if 'chg' in placeholder and isinstance(value, (int, float)):
                    # 将变化百分比格式化为百分数（假设原始数据已经是百分比形式，如0.15表示15%）
                    formatted_value = f"{round(value * 100, 2)}%"
                    print(f"替换变化百分比占位符 {{{placeholder}}} 为百分数格式: {formatted_value}", file=sys.stderr)
                elif isinstance(value, float):
                    formatted_value = str(round(value, 5))
                    print(f"替换占位符 {{{placeholder}}} 为值: {formatted_value}", file=sys.stderr)
                else:
                    formatted_value = str(value)
                    print(f"替换占位符 {{{placeholder}}} 为值: {formatted_value}", file=sys.stderr)
                
                # 在段落级别进行替换，然后重新构建runs
                paragraph.text = paragraph.text.replace('{' + placeholder + '}', formatted_value)
            else:
                print(f"值为None，将占位符 {{{placeholder}}} 设置为隐藏文本", file=sys.stderr)
                # 找到包含占位符的runs并设置为隐藏
                placeholder_text = '{' + placeholder + '}'
                full_text = paragraph.text
                if placeholder_text in full_text:
                    # 标记整个段落中包含此占位符的部分为隐藏
                    for run in paragraph.runs:
                        if any(char in run.text for char in placeholder_text):
                            run.font.hidden = True
        else:
            # 尝试解析旧格式的占位符（向后兼容）
            value = parse_legacy_placeholder(placeholder, data_mapping)
            if value is not None:
                # 检查是否为变化百分比数据（占位符包含'chg'）
                if 'chg' in placeholder and isinstance(value, (int, float)):
                    # 将变化百分比格式化为百分数（假设原始数据已经是百分比形式，如0.15表示15%）
                    formatted_value = f"{round(value * 100, 2)}%"
                    print(f"通过旧格式解析替换变化百分比占位符 {{{placeholder}}} 为百分数格式: {formatted_value}", file=sys.stderr)
                elif isinstance(value, float):
                    formatted_value = str(round(value, 5))
                    print(f"通过旧格式解析替换占位符 {{{placeholder}}} 为值: {formatted_value}", file=sys.stderr)
                else:
                    formatted_value = str(value)
                    print(f"通过旧格式解析替换占位符 {{{placeholder}}} 为值: {formatted_value}", file=sys.stderr)
                
                paragraph.text = paragraph.text.replace('{' + placeholder + '}', formatted_value)
            else:
                # 如果找不到对应的数据，设置为隐藏文本
                print(f"在数据映射中未找到占位符: {placeholder}，将设置为隐藏文本", file=sys.stderr)
                placeholder_text = '{' + placeholder + '}'
                full_text = paragraph.text
                if placeholder_text in full_text:
                    # 标记整个段落中包含此占位符的部分为隐藏
                    for run in paragraph.runs:
                        if any(char in run.text for char in placeholder_text):
                            run.font.hidden = True


def fill_word_template(base_json_path, lisan_json_path, template_path, output_path=None):
    """
    将base和lisan JSON数据填充到Word模板中
    Args:
        base_json_path: base数据JSON文件路径
        lisan_json_path: lisan数据JSON文件路径
        template_path: Word模板文件路径
        output_path: 输出文件路径，如果为None则使用默认路径
    Returns:
        字典，包含处理结果信息
    """
    try:
        log(f"开始处理Word模板填充，base文件: {base_json_path}, lisan文件: {lisan_json_path}, 模板文件: {template_path}")
        
        # 检查文件是否存在
        base_exists = base_json_path and os.path.exists(base_json_path)
        lisan_exists = lisan_json_path and os.path.exists(lisan_json_path)
        
        # 至少需要一个数据文件存在
        if not base_exists and not lisan_exists:
            log("Base和Lisan JSON文件都不存在，至少需要提供一个数据文件", "ERROR")
            return {"success": False, "error": "Base和Lisan JSON文件都不存在，至少需要提供一个数据文件"}
        
        if base_json_path and not base_exists:
            log(f"base JSON文件路径已提供但文件不存在: {base_json_path}", "WARNING")
            
        if lisan_json_path and not lisan_exists:
            log(f"lisan JSON文件路径已提供但文件不存在: {lisan_json_path}", "WARNING")
            
        if not os.path.exists(template_path):
            log(f"模板文件不存在: {template_path}", "ERROR")
            return {"success": False, "error": f"模板文件不存在: {template_path}"}
        
        # 读取base JSON数据（如果存在）
        base_data = None
        if base_exists:
            log("正在读取base JSON数据...")
            try:
                # 尝试以不同编码方式读取文件
                encodings = ['utf-8', 'utf-8-sig', 'gbk', 'cp1252']
                
                for encoding in encodings:
                    try:
                        log(f"尝试使用编码 {encoding} 读取base文件")
                        with open(base_json_path, 'r', encoding=encoding) as f:
                            base_data = json.load(f)
                        log(f"使用编码 {encoding} 成功读取base JSON数据")
                        break
                    except UnicodeDecodeError as ude:
                        log(f"编码 {encoding} 失败: {str(ude)}", "WARNING")
                        continue
                    except json.JSONDecodeError as jde:
                        log(f"JSON解析失败 (编码 {encoding}): {str(jde)}", "WARNING")
                        continue
                        
                if base_data is None:
                    raise Exception("所有编码方式都无法读取base文件")
                    
            except Exception as e:
                log(f"读取base JSON数据失败: {str(e)}", "ERROR")
                return {"success": False, "error": f"读取base JSON数据失败: {str(e)}"}
        else:
            log("跳过base JSON数据读取（文件不存在或未提供）")
        
        # 读取lisan JSON数据（如果存在）
        lisan_data = None
        if lisan_exists:
            log("正在读取lisan JSON数据...")
            try:
                encodings = ['utf-8', 'utf-8-sig', 'gbk', 'cp1252']
                for encoding in encodings:
                    try:
                        log(f"尝试使用编码 {encoding} 读取lisan文件")
                        with open(lisan_json_path, 'r', encoding=encoding) as f:
                            lisan_data = json.load(f)
                        log(f"使用编码 {encoding} 成功读取lisan JSON数据")
                        break
                    except UnicodeDecodeError as ude:
                        log(f"编码 {encoding} 失败: {str(ude)}", "WARNING")
                        continue
                    except json.JSONDecodeError as jde:
                        log(f"JSON解析失败 (编码 {encoding}): {str(jde)}", "WARNING")
                        continue
                        
                if lisan_data is None:
                    raise Exception("所有编码方式都无法读取lisan文件")
                    
            except Exception as e:
                log(f"读取lisan JSON数据失败: {str(e)}", "ERROR")
                return {"success": False, "error": f"读取lisan JSON数据失败: {str(e)}"}
        else:
            log("跳过lisan JSON数据读取（文件不存在或未提供）")
        
        # 检查base JSON数据格式（如果存在）
        if base_data is not None:
            if not isinstance(base_data, dict):
                log("base JSON数据格式不正确，不是一个字典", "ERROR")
                return {"success": False, "error": "base JSON数据格式不正确，不是一个字典"}
                
            if 'data' not in base_data:
                log("base JSON数据格式不正确，缺少'data'字段", "ERROR")
                return {"success": False, "error": "base JSON数据格式不正确，缺少'data'字段"}
        
        # 检查lisan JSON数据格式（如果存在）
        if lisan_data is not None:
            if not isinstance(lisan_data, dict):
                log("lisan JSON数据格式不正确，不是一个字典", "ERROR")
                return {"success": False, "error": "lisan JSON数据格式不正确，不是一个字典"}
                
            # lisan数据可能直接包含region数据，不一定有'data'字段
            log(f"lisan数据结构: {list(lisan_data.keys())[:10]}...")  # 显示前10个键
        
        # 打开Word模板
        log(f"正在打开Word模板: {template_path}")
        try:
            # 检查模板文件是否存在
            if not os.path.exists(template_path):
                error_msg = f"Word模板文件不存在: {template_path}"
                log(error_msg, "ERROR")
                return {"success": False, "error": error_msg}
                
            # 检查文件大小
            file_size = os.path.getsize(template_path)
            log(f"模板文件大小: {file_size} 字节")
            
            if file_size == 0:
                error_msg = f"Word模板文件为空: {template_path}"
                log(error_msg, "ERROR")
                return {"success": False, "error": error_msg}
                
            # 尝试打开文档
            log("尝试使用python-docx打开Word文档...")
            doc = Document(template_path)
            log("Word模板打开成功")
            log(f"文档包含 {len(doc.paragraphs)} 个段落和 {len(doc.tables)} 个表格")
        except Exception as e:
            log(f"打开Word模板失败: {str(e)}", "ERROR")
            import traceback
            log(f"错误详情: {traceback.format_exc()}", "ERROR")
            return {"success": False, "error": f"打开Word模板失败: {str(e)}"}
        
        # 创建数据映射字典
        file_data_mapping = {}
        
        # 处理base数据（如果存在）
        if base_data is not None:
            log("开始处理base JSON数据...")
            base_data_count = len(base_data['data']) if isinstance(base_data['data'], list) else 0
            log(f"base JSON数据包含{base_data_count}个文件数据项")
            
            for file_index, file_data in enumerate(base_data['data']):
                if not isinstance(file_data, list) or len(file_data) < 2:
                    log(f"跳过无效base数据项 #{file_index+1}，不是列表或长度小于2", "WARNING")
                    continue
                    
                # 获取文件名
                file_name = file_data[0]
                log(f"处理base文件 #{file_index+1}: {file_name}")
                
                # 检查是否为after_processed文件
                if 'after_processed' in file_name.lower():
                    # 解析after_processed文件名，例如 "Volunteer 5 condition 4 after_processed.xlsx" -> v5
                    match = re.search(r'volunteer\s+(\d+)', file_name.lower())
                    if match:
                        volunteer_num = int(match.group(1))
                        prefix = f"v{volunteer_num}"
                        log(f"解析after_processed文件名成功: {file_name} -> {prefix}")
                        
                        # 处理after_processed文件的特殊数据结构
                        item_count = 0
                        for item_index, item in enumerate(file_data[1:]):
                            if isinstance(item, dict):
                                # 处理'初始max'数据块
                                if '初始max' in item:
                                    initial_max_data = item['初始max']
                                    log(f"处理初始max数据: {list(initial_max_data.keys())}")
                                    
                                    # 遍历所有region数据
                                    for key, value in initial_max_data.items():
                                        if 'region' in key.lower():
                                            # 提取region号码
                                            region_match = re.search(r'region\s*(\d+)', key.lower())
                                            if region_match:
                                                region_num = region_match.group(1)
                                                
                                                # 判断是平均压强还是压强峰值
                                                if '平均压强' in key:
                                                    mapping_key = f"{prefix}st{region_num}a"
                                                    file_data_mapping[mapping_key] = value
                                                    log(f"添加初始max平均压强映射: {mapping_key} -> {value}")
                                                    item_count += 1
                                                elif '压强峰值' in key:
                                                    mapping_key = f"{prefix}st{region_num}m"
                                                    file_data_mapping[mapping_key] = value
                                                    log(f"添加初始max压强峰值映射: {mapping_key} -> {value}")
                                                    item_count += 1
                                
                                # 处理'一小时后max'数据块
                                elif '一小时后max' in item:
                                    after_hour_data = item['一小时后max']
                                    log(f"处理一小时后max数据: {list(after_hour_data.keys())}")
                                    
                                    # 遍历所有region数据
                                    for key, value in after_hour_data.items():
                                        if 'region' in key.lower():
                                            # 提取region号码
                                            region_match = re.search(r'region\s*(\d+)', key.lower())
                                            if region_match:
                                                region_num = region_match.group(1)
                                                
                                                # 判断是平均压强还是压强峰值
                                                if '平均压强' in key:
                                                    mapping_key = f"{prefix}af{region_num}a"
                                                    file_data_mapping[mapping_key] = value
                                                    log(f"添加一小时后max平均压强映射: {mapping_key} -> {value}")
                                                    item_count += 1
                                                elif '压强峰值' in key:
                                                    mapping_key = f"{prefix}af{region_num}m"
                                                    file_data_mapping[mapping_key] = value
                                                    log(f"添加一小时后max压强峰值映射: {mapping_key} -> {value}")
                                                    item_count += 1
                                
                                # 处理'变化百分比'数据块
                                elif '变化百分比' in item:
                                    change_percentage_data = item['变化百分比']
                                    log(f"处理变化百分比数据: {list(change_percentage_data.keys())}")
                                    
                                    # 遍历所有region数据
                                    for key, value in change_percentage_data.items():
                                        if 'region' in key.lower():
                                            # 提取region号码
                                            region_match = re.search(r'region\s*(\d+)', key.lower())
                                            if region_match:
                                                region_num = region_match.group(1)
                                                mapping_key = f"{prefix}chg{region_num}"
                                                file_data_mapping[mapping_key] = value
                                                log(f"添加变化百分比映射: {mapping_key} -> {value}")
                                                item_count += 1
                                
                                else:
                                    log(f"after_processed项目 #{item_index+1} 不包含已知的数据类型: {list(item.keys())}", "WARNING")
                            else:
                                log(f"after_processed项目 #{item_index+1} 不是字典类型，跳过", "WARNING")
                        
                        log(f"after_processed文件 {file_name} 处理完成，添加了 {item_count} 个数据映射")
                    else:
                        log(f"无法解析after_processed文件名: {file_name}，不符合'Volunteer X'格式", "WARNING")
                else:
                    # 解析普通文件名，例如 "Volunteer 5 condition 4.xlsx" -> v5c4
                    match = re.search(r'volunteer\s+(\d+)\s+condition\s+(\d+)', file_name.lower())
                    if match:
                        volunteer_num = int(match.group(1))
                        condition_num = int(match.group(2))
                        prefix = f"v{volunteer_num}c{condition_num}"
                        log(f"解析base文件名成功: {file_name} -> {prefix}")
                        
                        # 提取需要的数据
                        item_count = 0
                        for item_index, item in enumerate(file_data[1:]):
                            if isinstance(item, dict):
                                # 处理臀部左右_最大偏差行数据
                                if '臀部左右_最大偏差行' in item:
                                    max_deviation_data = item['臀部左右_最大偏差行']
                                    # 映射具体字段到对应的占位符
                                    if 'region 2压强峰值/kPa' in max_deviation_data:
                                        file_data_mapping[prefix + 's1b'] = max_deviation_data['region 2压强峰值/kPa']
                                        log(f"添加base数据映射: {prefix}s1b -> region 2压强峰值/kPa")
                                        item_count += 1
                                    if 'region 3压强峰值/kPa' in max_deviation_data:
                                        file_data_mapping[prefix + 's1c'] = max_deviation_data['region 3压强峰值/kPa']
                                        log(f"添加base数据映射: {prefix}s1c -> region 3压强峰值/kPa")
                                        item_count += 1
                                    if '左右侧压强峰值偏差' in max_deviation_data:
                                        file_data_mapping[prefix + 's1e'] = max_deviation_data['左右侧压强峰值偏差']
                                        log(f"添加base数据映射: {prefix}s1e -> 左右侧压强峰值偏差")
                                        item_count += 1
                                # 处理臀部左右_最大平均偏差行数据
                                elif '臀部左右_最大平均偏差行' in item:
                                    max_avg_deviation_data = item['臀部左右_最大平均偏差行']
                                    # 映射具体字段到对应的占位符
                                    if 'region 2平均压强/kPa' in max_avg_deviation_data:
                                        file_data_mapping[prefix + 's1f'] = max_avg_deviation_data['region 2平均压强/kPa']
                                        log(f"添加base数据映射: {prefix}s1f -> region 2平均压强/kPa")
                                        item_count += 1
                                    if 'region 3平均压强/kPa' in max_avg_deviation_data:
                                        file_data_mapping[prefix + 's1g'] = max_avg_deviation_data['region 3平均压强/kPa']
                                        log(f"添加base数据映射: {prefix}s1g -> region 3平均压强/kPa")
                                        item_count += 1
                                    if '左右侧平均压强偏差' in max_avg_deviation_data:
                                        file_data_mapping[prefix + 's1i'] = max_avg_deviation_data['左右侧平均压强偏差']
                                        log(f"添加base数据映射: {prefix}s1i -> 左右侧平均压强偏差")
                                        item_count += 1
                                # 处理七区_max行_数据 -> s2
                                elif '七区_max行_数据' in item:
                                    file_data_mapping[prefix + 's2'] = item['七区_max行_数据']
                                    log(f"添加base数据映射: {prefix}s2 -> 七区_max行_数据")
                                    item_count += 1
                                else:
                                    log(f"base项目 #{item_index+1} 不包含已知的数据类型: {list(item.keys())}", "WARNING")
                            else:
                                log(f"base项目 #{item_index+1} 不是字典类型，跳过", "WARNING")
                        
                        log(f"base文件 {file_name} 处理完成，添加了 {item_count} 个数据映射")
                    else:
                         log(f"无法解析base文件名: {file_name}，不符合'Volunteer X condition Y'格式", "WARNING")
        else:
            log("跳过base JSON数据处理（数据不存在）")
        
        # 处理lisan数据（如果存在）
        if lisan_data is not None:
            log("开始处理lisan JSON数据...")
            
            # 检查是否为新的单文件格式（包含fileName和lisan字段）
            if 'fileName' in lisan_data and 'lisan' in lisan_data:
                # 新的单文件格式处理
                log("使用新的单文件格式处理lisan数据")
                file_name = lisan_data['fileName']
                regions_data = lisan_data['lisan']
                
                log(f"处理lisan文件: {file_name}")
                
                # 解析文件名，例如 "Volunteer 2 condition 5.csv" -> v2c5
                match = re.search(r'volunteer\s+(\d+)\s+condition\s+(\d+)', file_name.lower())
                if match:
                    volunteer_num = int(match.group(1))
                    condition_num = int(match.group(2))
                    prefix = f"v{volunteer_num}c{condition_num}"
                    log(f"解析lisan文件名成功: {file_name} -> {prefix}")
                    
                    # 处理每个region的数据
                    if isinstance(regions_data, dict):
                        for region_key, region_data in regions_data.items():
                            if region_key.startswith('region_') and isinstance(region_data, dict):
                                # 提取region号码
                                region_match = re.search(r'region_(\d+)', region_key)
                                if region_match:
                                    region_num = region_match.group(1)
                                    
                                    # 为每种统计类型创建映射
                                    if '平均值' in region_data:
                                        pj_key = f"{prefix}pj{region_num}"
                                        file_data_mapping[pj_key] = region_data['平均值']
                                        log(f"添加lisan数据映射: {pj_key} -> 平均值 = {region_data['平均值']}")
                                    
                                    if '标准差' in region_data:
                                        bz_key = f"{prefix}bz{region_num}"
                                        file_data_mapping[bz_key] = region_data['标准差']
                                        log(f"添加lisan数据映射: {bz_key} -> 标准差 = {region_data['标准差']}")
                                    
                                    if '离散系数' in region_data:
                                        ls_key = f"{prefix}ls{region_num}"
                                        file_data_mapping[ls_key] = region_data['离散系数']
                                        log(f"添加lisan数据映射: {ls_key} -> 离散系数 = {region_data['离散系数']}")
                    else:
                        log(f"lisan文件 {file_name} 的数据格式不正确，不是字典类型", "WARNING")
                else:
                    log(f"无法解析lisan文件名: {file_name}，不符合'Volunteer X condition Y'格式", "WARNING")
            else:
                # 旧格式处理（向后兼容）
                log("使用旧格式处理lisan数据")
                for file_name, regions_data in lisan_data.items():
                    log(f"处理lisan文件: {file_name}")
                    
                    # 解析文件名，例如 "Volunteer 5 condition 4.xlsx" -> v5c4
                    match = re.search(r'volunteer\s+(\d+)\s+condition\s+(\d+)', file_name.lower())
                    if match:
                        volunteer_num = int(match.group(1))
                        condition_num = int(match.group(2))
                        prefix = f"v{volunteer_num}c{condition_num}"
                        log(f"解析lisan文件名成功: {file_name} -> {prefix}")
                        
                        # 处理每个region的数据
                        if isinstance(regions_data, dict):
                            for region_key, region_data in regions_data.items():
                                if region_key.startswith('region') and isinstance(region_data, dict):
                                    # 提取region号码
                                    region_match = re.search(r'region(\d+)', region_key)
                                    if region_match:
                                        region_num = region_match.group(1)
                                        
                                        # 为每种统计类型创建映射
                                        if '平均值' in region_data:
                                            pj_key = f"{prefix}pj{region_num}"
                                            file_data_mapping[pj_key] = region_data['平均值']
                                            log(f"添加lisan数据映射: {pj_key} -> 平均值 = {region_data['平均值']}")
                                        
                                        if '标准差' in region_data:
                                            bz_key = f"{prefix}bz{region_num}"
                                            file_data_mapping[bz_key] = region_data['标准差']
                                            log(f"添加lisan数据映射: {bz_key} -> 标准差 = {region_data['标准差']}")
                                        
                                        if '离散系数' in region_data:
                                            ls_key = f"{prefix}ls{region_num}"
                                            file_data_mapping[ls_key] = region_data['离散系数']
                                            log(f"添加lisan数据映射: {ls_key} -> 离散系数 = {region_data['离散系数']}")
                        else:
                            log(f"lisan文件 {file_name} 的数据格式不正确，不是字典类型", "WARNING")
                    else:
                        log(f"无法解析lisan文件名: {file_name}，不符合'Volunteer X condition Y'格式", "WARNING")
        else:
            log("跳过lisan JSON数据处理（数据不存在）")
        
        # 填充Word文档中的占位符
        log("开始填充Word文档中的占位符...")
        paragraph_count = 0
        placeholder_count = 0
        
        # 检查数据映射是否为空
        if not file_data_mapping:
            log("警告: 数据映射字典为空，没有可用于填充的数据", "WARNING")
        else:
            log(f"数据映射字典包含 {len(file_data_mapping)} 个键值对")
            # 打印前10个键值对作为示例
            sample_keys = list(file_data_mapping.keys())[:10]
            for key in sample_keys:
                log(f"数据映射示例: {key} -> {type(file_data_mapping[key])}")
        
        # 处理段落中的占位符
        log(f"开始处理 {len(doc.paragraphs)} 个段落中的占位符...")
        for i, paragraph in enumerate(doc.paragraphs):
            if re.search(r'\{([^}]+)\}', paragraph.text):
                placeholders = re.findall(r'\{([^}]+)\}', paragraph.text)
                log(f"处理段落 #{i+1}: 包含 {len(placeholders)} 个占位符, 文本: {paragraph.text[:50]}...")
                placeholder_count += len(placeholders)
                fill_paragraph_placeholders(paragraph, file_data_mapping)
                paragraph_count += 1
        
        log(f"段落处理完成: 处理了 {paragraph_count} 个包含占位符的段落，共 {placeholder_count} 个占位符")
        
        # 处理表格中的占位符
        log(f"开始处理 {len(doc.tables)} 个表格中的占位符...")
        table_count = 0
        table_placeholder_count = 0
        
        for table_index, table in enumerate(doc.tables):
            table_count += 1
            log(f"处理表格 #{table_index+1}，表格有 {len(table.rows)} 行 x {len(table.rows[0].cells) if table.rows else 0} 列")
            processed_cells = 0
            table_placeholders = 0
            
            for i, row in enumerate(table.rows):
                for j, cell in enumerate(row.cells):
                    cell_has_placeholder = False
                    cell_placeholders = 0
                    
                    for paragraph in cell.paragraphs:
                        if re.search(r'\{([^}]+)\}', paragraph.text):
                            placeholders = re.findall(r'\{([^}]+)\}', paragraph.text)
                            cell_has_placeholder = True
                            cell_placeholders += len(placeholders)
                            log(f"处理表格单元格[{i+1},{j+1}]中的段落: {paragraph.text[:30]}...")
                            fill_paragraph_placeholders(paragraph, file_data_mapping)
                    
                    if cell_has_placeholder:
                        processed_cells += 1
                        table_placeholders += cell_placeholders
            
            table_placeholder_count += table_placeholders
            log(f"表格 #{table_index+1} 处理完成: 处理了 {processed_cells} 个包含占位符的单元格，共 {table_placeholders} 个占位符")
        
        log(f"表格处理完成: 处理了 {table_count} 个表格，共 {table_placeholder_count} 个占位符")
        log(f"文档填充总结: 处理了 {paragraph_count} 个段落和 {table_count} 个表格，共填充了 {placeholder_count + table_placeholder_count} 个占位符")
        
        # 如果没有提供输出路径，则在桌面创建
        if not output_path:
            # 获取桌面路径
            desktop_path = os.path.join(os.path.expanduser('~'), 'Desktop')
            timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
            output_path = os.path.join(desktop_path, f"filled_template_{timestamp}.docx")
            log(f"未提供输出路径，将使用默认路径: {output_path}")
        else:
            log(f"使用指定的输出路径: {output_path}")
        
        # 确保输出目录存在
        output_dir = os.path.dirname(output_path)
        log(f"确保输出目录存在: {output_dir}")
        if not os.path.exists(output_dir):
            log(f"输出目录不存在，创建目录: {output_dir}")
            try:
                os.makedirs(output_dir)
                log(f"成功创建输出目录: {output_dir}")
            except Exception as e:
                log(f"创建输出目录失败: {str(e)}", "ERROR")
                return {"success": False, "error": f"创建输出目录失败: {str(e)}"}
        else:
            log(f"输出目录已存在: {output_dir}")
            # 检查目录是否可写
            if not os.access(output_dir, os.W_OK):
                log(f"输出目录没有写入权限: {output_dir}", "ERROR")
                return {"success": False, "error": f"输出目录没有写入权限: {output_dir}"}
        
        # 检查是否有同名文件且是否可以覆盖
        if os.path.exists(output_path):
            log(f"输出文件已存在，将被覆盖: {output_path}", "WARNING")
            try:
                # 尝试删除现有文件
                os.remove(output_path)
                log(f"已删除现有文件: {output_path}")
            except Exception as e:
                log(f"无法删除现有文件: {str(e)}", "ERROR")
                return {"success": False, "error": f"无法删除现有文件: {str(e)}"}
        
        # 保存文档
        log(f"正在保存文档到: {output_path}")
        try:
            doc.save(output_path)
            # 验证文件是否成功保存
            if os.path.exists(output_path):
                file_size = os.path.getsize(output_path)
                log(f"文档保存成功: {output_path}，文件大小: {file_size} 字节")
                return {"success": True, "output_file": output_path}
            else:
                log(f"错误：文件保存失败，无法在指定路径找到文件: {output_path}", "ERROR")
                return {"success": False, "error": "文件保存失败，无法在指定路径找到文件"}
        except Exception as e:
            log(f"保存文档失败: {str(e)}", "ERROR")
            import traceback
            log(f"错误详情: {traceback.format_exc()}", "ERROR")
            return {"success": False, "error": f"保存文档失败: {str(e)}"}
    
    except Exception as e:
        import traceback
        traceback_str = traceback.format_exc()
        print(f"错误详情: {traceback_str}")
        return {"success": False, "error": f"填充Word模板失败: {str(e)}"}


def main():
    """
    主函数，处理命令行参数
    """
    log("开始执行Word模板填充命令行工具", "INFO")
    if len(sys.argv) < 3:
        log("错误: 未提供足够的JSON文件路径", "ERROR")
        print(json.dumps({"success": False, "error": "缺少必要参数。用法: python fill_word_template.py <base_json_path> <lisan_json_path> [word_template_path] [output_path]\n注意：base_json_path或lisan_json_path可以设置为空字符串\"\"来跳过该文件"}, cls=NaNEncoder))
        return
    
    base_json_path = sys.argv[1] if sys.argv[1] != "" else None
    lisan_json_path = sys.argv[2] if sys.argv[2] != "" else None
    
    # 检查至少有一个文件路径被提供
    if base_json_path is None and lisan_json_path is None:
        error_msg = "错误: 必须至少提供Base JSON文件或Lisan JSON文件之一"
        log(error_msg, "ERROR")
        print(json.dumps({"success": False, "error": error_msg}, cls=NaNEncoder))
        return
    
    log(f"Base JSON文件路径: {base_json_path if base_json_path else '未提供'}")
    log(f"Lisan JSON文件路径: {lisan_json_path if lisan_json_path else '未提供'}")
    
    # 路径处理和验证
    try:
        # 处理Base JSON路径
        if base_json_path:
            # 规范化路径，处理不同操作系统的路径分隔符
            base_json_path = os.path.normpath(base_json_path)
            log(f"规范化后的Base JSON文件路径: {base_json_path}")
            
            # 转换为绝对路径
            base_json_path = os.path.abspath(base_json_path)
            log(f"Base绝对路径: {base_json_path}")
            
            # 检查路径的父目录权限
            base_parent_dir = os.path.dirname(base_json_path)
            log(f"Base父目录: {base_parent_dir}")
            
            if not os.path.exists(base_parent_dir):
                error_msg = f"Base父目录不存在: {base_parent_dir}"
                log(error_msg, "ERROR")
                print(json.dumps({"success": False, "error": error_msg}, cls=NaNEncoder))
                return
                
            if not os.access(base_parent_dir, os.R_OK):
                error_msg = f"没有读取Base父目录的权限: {base_parent_dir}"
                log(error_msg, "ERROR")
                print(json.dumps({"success": False, "error": error_msg}, cls=NaNEncoder))
                return
        
        # 处理Lisan JSON路径
        if lisan_json_path:
            # 规范化路径，处理不同操作系统的路径分隔符
            lisan_json_path = os.path.normpath(lisan_json_path)
            log(f"规范化后的Lisan JSON文件路径: {lisan_json_path}")
            
            # 转换为绝对路径
            lisan_json_path = os.path.abspath(lisan_json_path)
            log(f"Lisan绝对路径: {lisan_json_path}")
            
            # 检查路径的父目录权限
            lisan_parent_dir = os.path.dirname(lisan_json_path)
            log(f"Lisan父目录: {lisan_parent_dir}")
            
            if not os.path.exists(lisan_parent_dir):
                error_msg = f"Lisan父目录不存在: {lisan_parent_dir}"
                log(error_msg, "ERROR")
                print(json.dumps({"success": False, "error": error_msg}, cls=NaNEncoder))
                return
                
            if not os.access(lisan_parent_dir, os.R_OK):
                error_msg = f"没有读取Lisan父目录的权限: {lisan_parent_dir}"
                log(error_msg, "ERROR")
                print(json.dumps({"success": False, "error": error_msg}, cls=NaNEncoder))
                return
            
    except Exception as e:
        error_msg = f"路径处理失败: {str(e)}"
        log(error_msg, "ERROR")
        print(json.dumps({"success": False, "error": error_msg}, cls=NaNEncoder))
        return
    
    # 检查是否提供了模板文件路径
    template_path = None
    if len(sys.argv) > 3:
        template_path = sys.argv[3]
        log(f"提供的模板文件路径: {template_path}")
    else:
        log("未提供模板文件路径，将使用默认模板")
    
    # 检查是否提供了输出文件路径
    output_path = None
    if len(sys.argv) > 4:
        output_path = sys.argv[4]
        log(f"提供的输出文件路径: {output_path}")
    else:
        log("未提供输出文件路径，将使用默认输出路径")
    
    try:
        # 检查Base JSON文件是否存在（如果提供了路径）
        if base_json_path:
            if not os.path.exists(base_json_path):
                error_msg = f"Base JSON文件不存在: {base_json_path}"
                log(error_msg, "ERROR")
                print(json.dumps({"success": False, "error": error_msg}, cls=NaNEncoder))
                return
            else:
                # 检查文件权限
                if not os.access(base_json_path, os.R_OK):
                    error_msg = f"没有读取Base JSON文件的权限: {base_json_path}"
                    log(error_msg, "ERROR")
                    print(json.dumps({"success": False, "error": error_msg}, cls=NaNEncoder))
                    return
                    
                # 检查Base JSON文件大小
                try:
                    file_size = os.path.getsize(base_json_path)
                    log(f"Base JSON文件存在，大小: {file_size} 字节")
                    if file_size == 0:
                        error_msg = f"Base JSON文件为空: {base_json_path}"
                        log(error_msg, "ERROR")
                        print(json.dumps({"success": False, "error": error_msg}, cls=NaNEncoder))
                        return
                except OSError as e:
                    error_msg = f"无法获取Base文件大小: {base_json_path}, 错误: {str(e)}"
                    log(error_msg, "ERROR")
                    print(json.dumps({"success": False, "error": error_msg}, cls=NaNEncoder))
                    return
        
        # 检查Lisan JSON文件是否存在（如果提供了路径）
        if lisan_json_path:
            if not os.path.exists(lisan_json_path):
                error_msg = f"Lisan JSON文件不存在: {lisan_json_path}"
                log(error_msg, "ERROR")
                print(json.dumps({"success": False, "error": error_msg}, cls=NaNEncoder))
                return
            else:
                # 检查文件权限
                if not os.access(lisan_json_path, os.R_OK):
                    error_msg = f"没有读取Lisan JSON文件的权限: {lisan_json_path}"
                    log(error_msg, "ERROR")
                    print(json.dumps({"success": False, "error": error_msg}, cls=NaNEncoder))
                    return
                    
                # 检查Lisan JSON文件大小
                try:
                    file_size = os.path.getsize(lisan_json_path)
                    log(f"Lisan JSON文件存在，大小: {file_size} 字节")
                    if file_size == 0:
                        error_msg = f"Lisan JSON文件为空: {lisan_json_path}"
                        log(error_msg, "ERROR")
                        print(json.dumps({"success": False, "error": error_msg}, cls=NaNEncoder))
                        return
                except OSError as e:
                    error_msg = f"无法获取Lisan文件大小: {lisan_json_path}, 错误: {str(e)}"
                    log(error_msg, "ERROR")
                    print(json.dumps({"success": False, "error": error_msg}, cls=NaNEncoder))
                    return
        
        # 如果没有提供模板文件路径，使用默认模板
        if template_path is None or not os.path.exists(template_path):
            # 获取当前脚本所在目录
            script_dir = os.path.dirname(os.path.abspath(__file__))
            log(f"脚本所在目录: {script_dir}")
            template_path = os.path.join(script_dir, "result-template.docx")
            log(f"尝试使用默认模板: {template_path}")
            
            # 检查默认模板是否存在
            if not os.path.exists(template_path):
                error_msg = f"默认模板文件不存在: {template_path}"
                log(error_msg, "ERROR")
                print(json.dumps({"success": False, "error": error_msg}, cls=NaNEncoder))
                return
            else:
                log(f"找到默认模板: {template_path}")
                # 检查模板文件大小
                template_size = os.path.getsize(template_path)
                log(f"默认模板文件大小: {template_size} 字节")
                if template_size == 0:
                    error_msg = "默认模板文件为空"
                    log(error_msg, "ERROR")
                    print(json.dumps({"success": False, "error": error_msg}, cls=NaNEncoder))
                    return
        else:
            log(f"使用指定的模板文件: {template_path}")
            # 检查模板文件大小
            template_size = os.path.getsize(template_path)
            log(f"模板文件大小: {template_size} 字节")
            if template_size == 0:
                error_msg = "模板文件为空"
                log(error_msg, "ERROR")
                print(json.dumps({"success": False, "error": error_msg}, cls=NaNEncoder))
                return
        
        # 填充Word模板
        log(f"开始调用fill_word_template函数处理数据...", "INFO")
        result = fill_word_template(base_json_path, lisan_json_path, template_path, output_path)
        log(f"处理完成，结果: {result}")
        print(json.dumps(result, cls=NaNEncoder))
    except Exception as e:
        log(f"执行过程中发生未捕获的异常: {str(e)}", "ERROR")
        import traceback
        log(f"错误详情: {traceback.format_exc()}", "ERROR")
        print(json.dumps({"success": False, "error": str(e)}, cls=NaNEncoder))


if __name__ == "__main__":
    main()